#include "Layer.h"
#include "Helper.h"
#include "LearningRateFunctions/LinearFunction.h"

using namespace NeuralPlusPlus::Core;
INeuron* NeuralPlusPlus::Core::Layer::operator[]( int index )
	{
	return Neurons[index];
	}

double NeuralPlusPlus::Core::Layer::LearningRate()
	{
	return LearningRateFunction->InitialLearningRate;
	}

NeuralPlusPlus::Core::Layer::Layer( int neuronCount )
	{
	Helper::ValidatePositive(neuronCount, "neuronCount");
	this->Initializer = NULL;
	this->LearningRateFunction = new LinearFunction(0.3, 0.05);
	this->Neurons = new INeuron*[neuronCount];
	this->NeuronsLength = neuronCount;
	}

void NeuralPlusPlus::Core::Layer::SetInput( double* input )
	{
	for (int i = 0; i < NeuronsLength; i++)
		{
		Neurons[i]->Input = input[i];
		}
	}

double* NeuralPlusPlus::Core::Layer::GetOutput()
	{
	double *output = new double[NeuronsLength];
	for (int i = 0; i < NeuronsLength; i++)
		{
		output[i] = Neurons[i]->Output;
		}
	return output;
	}

void NeuralPlusPlus::Core::Layer::SetLearningRate( double learningRate )
	{
	SetLearningRate(learningRate, learningRate);
	}

void NeuralPlusPlus::Core::Layer::SetLearningRate( double initialLearningRate, double finalLearningRate )
	{
	SetLearningRate(new LinearFunction(initialLearningRate, finalLearningRate));
	}

void NeuralPlusPlus::Core::Layer::SetLearningRate( AbstractFunction *learningRateFunction )
	{
	Helper::ValidateNotNull(learningRateFunction, "learningRateFunction");
	delete this->LearningRateFunction;
	this->LearningRateFunction = learningRateFunction;
	}

void NeuralPlusPlus::Core::Layer::Run()
	{
	for (int i = 0; i < NeuronsLength; i++)
		{
		Neurons[i]->Run();
		}
	}

void NeuralPlusPlus::Core::Layer::Learn( int currentIteration, int trainingEpochs )
	{
	double effectiveRate = LearningRateFunction->GetLearningRate(currentIteration, trainingEpochs);
	for (int i = 0; i < NeuronsLength; i++)
		{
		Neurons[i]->Learn(effectiveRate);
		}
	}

NeuralPlusPlus::Core::Layer::~Layer()
	{
	for (int i=0;i<NeuronsLength;i++)
		{
		delete Neurons[i];
		Neurons[i] = NULL;
		}
	delete[] Neurons;
	Neurons = NULL;

	delete Initializer;
	Initializer = NULL;
	delete LearningRateFunction;
	LearningRateFunction = NULL;
	}